﻿using Scanner.Eth;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace scanner_eth
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("eth addr scanner.");

            System.Threading.ThreadPool.QueueUserWorkItem((s) =>
            {
                System.Threading.Tasks.Task.WaitAll(ScanWork());
            });

            while (true)
            {
                Console.Write(">");
                var l = Console.ReadLine();
                if (l == "exit")
                {
                    return;
                }
            }
        }
        static uint GetCurCount()
        {
            if (System.IO.File.Exists("eth_count.txt"))
            {
                var count = uint.Parse(System.IO.File.ReadAllText("eth_count.txt"), System.Globalization.NumberStyles.HexNumber);
                return count;
            }
            return 0;
        }
        static void SetCurCount(uint count)
        {
            System.IO.File.WriteAllText("eth_count.txt", count.ToString("X08"));
        }
        static async Task ScanWork()
        {
            pri_rpc.Init();


            Dictionary<string, bool> addrs = new Dictionary<string, bool>();
            List<string> lines = new List<string>();

            var serverCount = await pri_rpc.GetBlockCountAsync();
            var serverMaxCount = await pri_rpc.GetHeightAsync();
            uint curCount = GetCurCount();
            Console.WriteLine("blockcount=" + curCount + "/" + serverCount + "/" + serverMaxCount);

            DateTime time = DateTime.Now;
            DateTime time2 = time;//每10s log一次
            while (true)
            {

                if (curCount < serverCount)
                {
                    try
                    {
                        await pri_rpc.GetBlockAsync(curCount, addrs, lines);
                    }
                    catch (Exception err)
                    {
                        Console.WriteLine("got net error:" + err.Message);
                        continue;
                    }
                    curCount++;

                    var perblockfile = 0x1000;//4k
                    //地址太多了，改4k一格吧 //4k存一格文件
                    if (curCount != 0 && curCount % perblockfile == 0)//6w清理一次地址缓存
                    {
                        //并刷一下高度
                        serverCount = await pri_rpc.GetBlockCountAsync();

                        addrs.Clear();

                        Console.Clear();
                        Console.WriteLine("Finish " + curCount.ToString("X08"));
                    }
                    if (curCount % 0x200 == 0)//512 log 一次
                    {
                        //time log
                        DateTime time1 = DateTime.Now;
                        Console.WriteLine("blockcount=" + curCount + "/" + serverCount + "/" + serverMaxCount + " delta=" + (time1 - time).TotalSeconds);
                        time = time1;
                        time2 = time1;

                        //限制一下去重集的总大小，最大16M条记录
                        if (addrs.Count > 0x1000000)
                            addrs.Clear();
                        //addr log

                        var filename = "addrs_eth" + "_" + ((curCount / perblockfile) * perblockfile).ToString("X08") + ".txt";
                        System.IO.File.AppendAllLines(filename, lines.ToArray());
                        lines.Clear();
                        //height  log
                        SetCurCount(curCount);
                    }
                    DateTime times = DateTime.Now;
                    if ((times - time2).TotalSeconds > 10)
                    {
                        time2 = times;
                        Console.WriteLine("10s " + curCount + "/" + serverCount + "/" + serverMaxCount);
                    }
                }
                else
                {
                    //30秒刷新高度
                    DateTime time1 = DateTime.Now;
                    if ((time1 - time).TotalSeconds > 30)
                    {
                        serverCount = await pri_rpc.GetBlockCountAsync();
                        serverMaxCount = await pri_rpc.GetHeightAsync();
                        time = time1;
                    }
                    System.Threading.Thread.Sleep(100);
                }
            }



        }
    }
}
